package lmteam.documentdataservice;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.PreparedStatement;

import lmteam.common.*;

import org.apache.commons.logging.Log;
import org.apache.axis.components.logger.LogFactory;

import java.io.*;
import java.util.Vector;


public class DocumentDataProcessor
    implements IDataAccess
{
    private Connection connection;
    private Statement  statement;
    private PreparedStatement prestatement;

    private final String databaseloc = "jdbc:sqlite:lmteamdatabase.db";

    private static Log log = LogFactory.getLog("IUserAccessSoapBindingImpl");

    public DocumentDataProcessor()
    {
	
    }

    public boolean add(lmteam.common.Document document, java.lang.String filename, java.lang.String author) throws java.rmi.RemoteException
    {
	String queryString;
	byte[] blob;
	int ret;
	OutputStream ostream;

	System.out.println("serializing....");
	blob = serializeDocument(document);	      
	Document doc2 = deserializeDocument( blob);
	System.out.println("output is <<<" + blob.length + ">>>");

	queryString = "INSERT INTO documents (filename,author,document) values (?,?,?);";
	try
	    {
      		Class.forName("org.sqlite.JDBC");

		connection = DriverManager.getConnection(databaseloc);
		prestatement = connection.prepareStatement( queryString );
		prestatement.setString(1, filename );
		prestatement.setString(2, author );
		prestatement.setBytes(3, blob);
		
		System.out.println("About to execute....");
		ret = prestatement.executeUpdate();
	
		ret = 0; // reset this to all good
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {	
			prestatement.close();
			connection.close();
		    }
		catch (Exception e)
		    {       
			e.printStackTrace();
		    }
	    }

        return (ret == 0);
    }

    public lmteam.common.Document get(java.lang.String filename) throws java.rmi.RemoteException 
    {
	String queryString;
	ResultSet resultSet;
	byte[] blob;
	int ret;
	Document doc;

	queryString = "SELECT * FROM documents WHERE filename=\'" + filename + "\';";
	resultSet = null;
	doc = null;
	try
	    {
      		Class.forName("org.sqlite.JDBC");
		connection = DriverManager.getConnection(databaseloc);
		statement = connection.createStatement();
	        resultSet = statement.executeQuery(queryString);
		
		ret = 0; // reset this to all good
		
		if ( resultSet.isClosed() != true )
		    {
       			resultSet.next();
						
			System.out.println("resultSet is <" + resultSet.getString("filename") + ">" );
			System.out.println("resultSet is <" + resultSet.getString("author") + ">" );
			//System.out.println("resultSet is <" + resultSet.getString("document").length() + ">" );
			
			doc = deserializeDocument( resultSet.getBytes( "document" ) );
		    }
		
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {
			System.out.println("Closing");
			if ( resultSet != null )
			    if ( resultSet.isClosed() == false )
				resultSet.close();
			statement.close();
			connection.close();
		    }
		catch (Exception e)
		    {
			e.printStackTrace();
		    }
	    }


        return doc;
    }

    public boolean delete(java.lang.String filename) throws java.rmi.RemoteException 
    {
	String queryString;
	int ret;

	queryString = "DELETE FROM documents WHERE filename=\'" + filename + "\';";
	try
	    {
      		Class.forName("org.sqlite.JDBC");
		connection = DriverManager.getConnection(databaseloc);
		statement = connection.createStatement();
	        ret = statement.executeUpdate(queryString);
	
		System.out.println("ret (Delete) is " + ret );
		ret = 0; // reset this to all good
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {
			System.out.println("Closing - 3");
			statement.close();
			connection.close();
		    }
		catch (Exception e)
		    {
			e.printStackTrace();
		    }
	    }

	return (ret == 0);
    }

    public boolean update(java.lang.String filename, lmteam.common.User name, lmteam.common.Role role, boolean add) throws java.rmi.RemoteException 
    {
	Document doc;
	byte[] blob;
	String queryString;
	int ret;

	doc = get( filename ); // reuse the other method 

	if ( role.isApprover() == true )
	    {
		doc.setApprover( name );
	    }
	else if ( role.isReviewer() == true )
	    {
		User[] revs = doc.getReviewer();
		Vector<User> vecr = new Vector<User>();
		if ( revs != null )
		    for ( int i = 0; i < revs.length; ++i )
			vecr.add( revs[i] );
		else
		    revs = new User[1];
		vecr.add( name );
		doc.setReviewer( vecr.toArray(revs) );
	    }
	else
	    {
		return false;
	    }

	blob = serializeDocument(doc);
	queryString = "UPDATE documents SET document=? WHERE filename=\'" + filename + "\';";
	try
	    {
      		Class.forName("org.sqlite.JDBC");
		connection = DriverManager.getConnection(databaseloc);
		prestatement = connection.prepareStatement( queryString );
		prestatement.setBytes(1, blob );
	        ret = prestatement.executeUpdate();
	
		System.out.println("ret (update) is " + ret );
		ret = 0; // reset this to all good
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {
			System.out.println("Closing - 3");
			prestatement.close();
			connection.close();
		    }
		catch (Exception e)
		    {
			e.printStackTrace();
		    }
	    }

	return (ret == 0);
    }

    public boolean update(java.lang.String filename, lmteam.common.Comment comment, boolean add) throws java.rmi.RemoteException 
    {
	Document doc;
	byte[] blob;
	String queryString;
	int ret;
	doc = get(filename ); // reuse the other method 

	Comment[] comms = doc.getComments();
	Vector<Comment> vecr = new Vector<Comment>();
	if ( comms != null )
	    for ( int i = 0; i < comms.length; ++i )
		vecr.add( comms[i] );
	else
	    comms = new Comment[1];
	vecr.add( comment );
	doc.setComments( vecr.toArray(comms) );

	blob = serializeDocument(doc);

	queryString = "UPDATE documents SET document=? WHERE filename=\'" + filename + "\';";
	try
	    {
      		Class.forName("org.sqlite.JDBC");
		connection = DriverManager.getConnection(databaseloc);
		prestatement = connection.prepareStatement( queryString );
		prestatement.setBytes(1, blob );
	        ret = prestatement.executeUpdate();

		System.out.println("ret (update) is " + ret );
		ret = 0; // reset this to all good
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {
			System.out.println("Closing - 3");
			statement.close();
			connection.close();
		    }
		catch (Exception e)
		    {
			e.printStackTrace();
		    }
	    }

	return (ret == 0);
    }

    public boolean update(java.lang.String filename, int grade) throws java.rmi.RemoteException 
    {
	Document doc;
	byte[] blob;
	String queryString;
	int ret;

	doc = get(filename ); // reuse the other method 

	doc.setGrade( grade );

	blob = serializeDocument(doc);
	queryString = "UPDATE documents SET document=? WHERE filename=\'" + filename + "\';";
	try
	    {
      		Class.forName("org.sqlite.JDBC");
		connection = DriverManager.getConnection(databaseloc);
		prestatement = connection.prepareStatement( queryString );
		prestatement.setBytes(1, blob );
	        ret = prestatement.executeUpdate();
	
		System.out.println("ret (update) is " + ret );
		ret = 0; // reset this to all good
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {
			System.out.println("Closing - 3");
			statement.close();
			connection.close();
		    }
		catch (Exception e)
		    {
			e.printStackTrace();
		    }
	    }

	return (ret == 0);
    }

    public boolean update(java.lang.String filename, boolean pass) throws java.rmi.RemoteException 
    {
	Document doc;
	byte[] blob;
	String queryString;
	int ret;
	int grade;

	doc = get(filename ); // reuse the other method 
	
	if ( pass )
	    grade = 100;
	else
	    grade = 0;
		
	doc.setGrade( grade );

	blob = serializeDocument(doc);
	queryString = "UPDATE documents SET document=? WHERE filename=\'" + filename + "\';";
	try
	    {
      		Class.forName("org.sqlite.JDBC");
		connection = DriverManager.getConnection(databaseloc);
		prestatement = connection.prepareStatement( queryString );
		prestatement.setBytes(1, blob );
	        ret = prestatement.executeUpdate();
	
		System.out.println("ret (update) is " + ret );
		ret = 0; // reset this to all good
	    }
	catch (Exception e)
	    {
		e.printStackTrace();
		ret = -1;
	    }
	finally
	    {
		try
		    {
			System.out.println("Closing - 3");
			statement.close();
			connection.close();
		    }
		catch (Exception e)
		    {
			e.printStackTrace();
		    }
	    }

	return (ret == 0);
    }

    private byte[] serializeDocument( Document doc )
    {
	try
	    {
		ByteArrayOutputStream baos;
		baos = new ByteArrayOutputStream();
		
		ObjectOutputStream oos = new ObjectOutputStream( baos );
		oos.writeObject( doc );
		oos.close();
		return baos.toByteArray();
	    }
	catch (Exception e)
	    {
		System.out.println("serializeDocument failed");
		e.printStackTrace();
	    }
	return null;
    }

    private Document deserializeDocument( byte[] in )
    {
	try
	    {
		ByteArrayInputStream bais;
		bais = new ByteArrayInputStream( in );
		ObjectInputStream ois = new ObjectInputStream( bais );
		Document doc;
		
		doc = (Document) ois.readObject();
		ois.close();
		
		return doc;
	    }
	catch (Exception e)
	    {
		System.out.println("deserializeDocument failed");
		e.printStackTrace();
	    }
	return null;
    }

}